package cn.stazxr.core.aspect;

import cn.stazxr.annotation.HasPermission;
import cn.stazxr.annotation.HasRole;
import cn.stazxr.constants.HttpConstant;
import cn.stazxr.core.RedisTemplate;
import cn.stazxr.exception.PermissionNeedHasAndPermissionException;
import cn.stazxr.exception.RoleNeedHasAndPermissionException;
import com.fasterxml.jackson.core.type.TypeReference;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.List;
import java.util.Objects;

import static cn.stazxr.constants.RedisKeyConstant.PERM_PREFIX;
import static cn.stazxr.constants.RedisKeyConstant.ROLE_PREFIX;

/**
 * @author talentestors
 * @version 1.0
 * @since 2025.11.02
 **/
@Component
@Aspect
public class PermissionAspect {

	@Autowired
	private RedisTemplate redisTemplate;

	/**
	 * 执行接口所需角色的切面
	 * @param joinPoint
	 * @param hasRole
	 */
	@Before("@annotation(hasRole)")
	public void roleBefore(JoinPoint joinPoint, HasRole hasRole) {
		// 获取当前方法所需要的角色
		String[] needRoles = hasRole.value();
		// 获得拥有的角色
		HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
		String token = request.getHeader(HttpConstant.AUTHORIZATION);
		List<String> hasRoles = redisTemplate.getObject(ROLE_PREFIX + token, new TypeReference<>() {});
		// 只要所需的角色有一个在你拥有的角色中就放行
		boolean flag = false;
		for (String needRole : needRoles) {
			if (hasRoles.contains(needRole)) {
				flag = true;
				break;
			}
		}
		if (!flag) {
			throw new RoleNeedHasAndPermissionException(needRoles);
		}
	}

	@Before("@annotation(hasPermission)")
	public void roleBefore(JoinPoint joinPoint, HasPermission hasPermission) {
		// 获取当前方法所需要的权限
		String[] needPermissions = hasPermission.value();
		// 获得拥有的权限
		HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
		String token = request.getHeader(HttpConstant.AUTHORIZATION);
		List<String> hasPermissions = redisTemplate.getObject(PERM_PREFIX + token, new TypeReference<>() {});
		// 只要所需的角色有一个在你拥有的角色中就放行
		boolean flag = false;
		for (String needRole : needPermissions) {
			if (hasPermissions.contains(needRole)) {
				flag = true;
				break;
			}
		}
		if (!flag) {
			throw new PermissionNeedHasAndPermissionException(needPermissions);
		}
	}

}
